NEAR OST_TASK_STATE     OS_state    __osa30_near;

#define OS_Init_ProcSpec()      // Empty macro for PICC18

/**************************************************************************************************
 * 
 *  R E T U R N   F U N C T I O N S   F O R   P I C C 1 8
 *
 **************************************************************************************************/

void _OS_ClrReadySetClrCanContinue (void);

/************************************************************************/
/* Save return address and return to scheduler                          */
/************************************************************************/

void OS_SchedRetPoint (void)
{
    _OS_SET_FSR_CUR_TASK();
    _OS_SavePC();
    _OS_bTaskReady = 1;
    asm("    global _OS_SchedRetPointNoSave   ");
    asm("_OS_SchedRetPointNoSave:             ");
    _PIC18_POP();
}


/************************************************************************/
/*                                                                      */
/************************************************************************/


asm("   global  _OS_ClearReady");
asm("_OS_ClearReady:     ");
asm("   clrf    __OS_temp, c    ");
asm("   global  __OS_ClrReadySetClrCanContinue  ");
asm("   goto    __OS_ClrReadySetClrCanContinue  ");

/************************************************************************/
/*                                                                      */
/************************************************************************/
asm("   global  _OS_ClearReadySetCanContinue");
asm("_OS_ClearReadySetCanContinue:     ");
asm("   setf    __OS_temp, c    ");
asm("   global  __OS_ClrReadySetClrCanContinue  ");
asm("   goto    __OS_ClrReadySetClrCanContinue  ");


//------------------------------------------------------------------------------
// Addition function. Called only by GOTO from:
//      OS_ClearReady()
//      OS_ClearReadySetCanContinue()
// Stack has pointer of task who called these services
//------------------------------------------------------------------------------
void _OS_ClrReadySetClrCanContinue (void)
{


    OS_Flags.bEventError = 0;
    
    _OS_SET_FSR_CUR_TASK();
    _OS_SavePC();

    _OS_bTaskReady = 0;

    #if defined(OS_ENABLE_TTIMERS)
        _OS_bTaskCanContinue = 0;
        if (_OS_temp & 0x01) _OS_bTaskCanContinue = 1;
    #endif

}
















/**************************************************************************************************
 * 
 * S E T   F S R   T O   P O I N T    O S _ C U R _ T A S K
 *
 * (for reduce used ROM)
 *
 **************************************************************************************************/

asm("   global __OS_SET_FSR_CUR_TASK        ");
asm("__OS_SET_FSR_CUR_TASK:                 ");
    _PIC18_ERRATA_NOP();
    asm("       movf        __OS_CurTask+0, w, c");
    asm("       movwf       __fsr + 0, c        ");
#if OS_BANK_TASKS == 0
    asm("       clrf        __fsr + 1, c        ");
#else 
    asm("       movf        __OS_CurTask+1, w, c");
    asm("       movwf       __fsr + 1, c        ");
#endif
    asm("       return                          ");



















/**************************************************************************************************
 * 
 * C O U N T I N G    S E M A P H O R E S
 *
 * (OS_ENABLE_CSEM must be defined in OSAcfg.h)
 *
 **************************************************************************************************/


//------------------------------------------------------------------------------
#ifdef OS_ENABLE_CSEM
//------------------------------------------------------------------------------
    

    /************************************************************************/
    /* Increase semaphore's value by 1                                      */
    /************************************************************************/
    //------------------------------------------------------------------------------
    #define _OS_SignalCSem_DEFINED
    //------------------------------------------------------------------------------
    void _OS_SignalCSem (OST_CSEM *pCSem)
    {
        __OS_CSEM_DI();
        OS_Flags.bEventError = 0;               // Counting semaphore overflow bit

        //------------------------------------------------------------------------------
        // 
        #if OS_CSEM_SIZE == 1
    
            _fsr = (_FSR_TYPE)pCSem;
            _indf++;
            if (!_indf)
            {
                _indf--;
                OS_Flags.bEventError = 1;   // Set overflow bit
            }
        //------------------------------------------------------------------------------
        // For two- and four-bytes semaphores
        // 
        #else 
            (*pCSem)++;
            if (!*pCSem) {          
                (*pCSem) = -1;
                OS_Flags.bEventError = 1;   // Set overflow bit
            }
        #endif
        //------------------------------------------------------------------------------

        __OS_CSEM_RI();
    }


    //------------------------------------------------------------------------------
    #if defined(OS_ENABLE_INT_CSEM)
    //------------------------------------------------------------------------------
    #define _OS_IntSignalCSem_DEFINED
    //------------------------------------------------------------------------------
    void _OS_IntSignalCSem (OST_CSEM *pCSem)
    {
        OS_Flags.bEventError = 0;               // Counting semaphore overflow bit

        //------------------------------------------------------------------------------
        // 
        #if OS_CSEM_SIZE == 1
    
            _fsr = (_FSR_TYPE)pCSem;
            _indf++;
            if (!_indf)
            {
                _indf--;
                OS_Flags.bEventError = 1;   // Set overflow bit
            }
        //------------------------------------------------------------------------------
        // For two- and four-bytes semaphores
        // 
        #else 
            (*pCSem)++;
            if (!*pCSem) {          
                (*pCSem) = -1;
                OS_Flags.bEventError = 1;   // Set overflow bit
            }
        #endif
        //------------------------------------------------------------------------------
    }

    #endif


//------------------------------------------------------------------------------
#endif      // OS_INABLE_CSEM
//------------------------------------------------------------------------------
    









/****************************************************************************************************
 * 
 * D I S A B L E   I N T E R R U P T S   W I T H    S A V I N G   G I E H : G I E L  
 * 
 * char OS_DI (void)   
 *
 ****************************************************************************************************/
/****************************************************************************************************
 * 
 * R E S T O R E   S A V E D   I N    O S _ D I ( )   I N T E R R U P T S
 * 
 * void OS_RI (char)   
 *
 ****************************************************************************************************/
//------------------------------------------------------------------------------
#define OS_DI_DEFINED
//------------------------------------------------------------------------------
asm("   global _OS_DI           ");
asm("_OS_DI:                    ");
asm("   dw      0xFFFF          ");
asm("   movf    __intcon, w, c   ");
asm("   andlw   0xC0            ");
asm("_DIH_REPEAT:               ");
asm("   bcf     __intcon, 7, c   ");
asm("   btfsc   __intcon, 7, c   ");
asm("   bra     _DIH_REPEAT     ");

asm("   btfss   __rcon, 7, c     ");
asm("   bra     _DI_EXIT        ");
asm("_DIL_REPEAT:               ");
asm("   bcf     __intcon, 6, c   ");
asm("   btfsc   __intcon, 6, c   ");
asm("   bra     _DIL_REPEAT     ");
asm("_DI_EXIT:                  ");
asm("   return                  ");
asm("   dw      0xFFFF          ");


asm("   global  _OS_RI          ");
asm("_OS_RI:                    ");
asm("   dw      0xFFFF          ");
asm("   btfsc   _WREG, 7, c     ");
asm("   bsf     __intcon, 7, c   ");
asm("   btfsc   __rcon, 7, c     ");
asm("   btfss   __wreg, 6, c     ");
asm("   bra     _RI_EXIT        ");
asm("   bsf     __intcon, 6, c   ");
asm("_RI_EXIT:                  ");
asm("   return                  ");
asm("   dw      0xFFFF          ");














 
    
    
/****************************************************************************************************
 * 
 * C R I T I C A L   S E C T I O N S   W O R K
 *
 ****************************************************************************************************/
//------------------------------------------------------------------------------
#ifdef OS_ENABLE_CRITICAL_SECTION
//------------------------------------------------------------------------------
    
/************************************************************************/
/* Enter critical section                                               */
/************************************************************************/
//------------------------------------------------------------------------------
#define OS_EnterCriticalSection_DEFINED
//------------------------------------------------------------------------------
void OS_EnterCriticalSection (void)
{
    _OST_INT_TYPE temp;
    temp = OS_DI();
    OS_Flags.bInCriticalSection = 1; 

    OS_Flags.bGIE_CTemp = 0;
    if (temp & 0x80) OS_Flags.bGIE_CTemp = 1;

    OS_Flags.bGIEL_CTemp = 0;
    if (temp & 0x40) OS_Flags.bGIEL_CTemp = 1;
}

/************************************************************************/
/* Leave critical section                                               */
/************************************************************************/
//------------------------------------------------------------------------------
#define OS_LeaveCriticalSection_DEFINED
//------------------------------------------------------------------------------
void OS_LeaveCriticalSection (void)
{
    char temp;
    OS_Flags.bInCriticalSection = 0; 
    temp = 0;
    if (OS_Flags.bGIE_CTemp) temp |= 0x80;
    if (OS_Flags.bGIEL_CTemp) temp |= 0x40;
    OS_RI(temp);
}

//------------------------------------------------------------------------------
#endif      //     #ifdef OS_ENABLE_CRITICAL_SECTION
//------------------------------------------------------------------------------


















//------------------------------------------------------------------------------
#ifdef OS_ENABLE_TTIMERS

/****************************************************************************************************
 * 
 *  D E L A Y S   W O R K 
 *
 ****************************************************************************************************/
/************************************************************************/
/*                                                                      */
/* Init task timer for counting                                         */
/* (internal system function)                                           */
/*                                                                      */
/************************************************************************/
//------------------------------------------------------------------------------
#define _OS_InitDelay_DEFINED
//------------------------------------------------------------------------------
void _OS_InitDelay (_OST_TTIMER Delay)
{

    _OS_bTaskCanContinue = 0;
    _OS_bTaskDelay = 0;         // Clear bDelay to prevent timer changing in interrupt
    _OS_SET_FSR_CUR_TASK();
    _indf = *((near char*)&OS_state);

    if (Delay)
    {

        Delay ^= -1;
        Delay ++;
        
        _OS_CurTask->Timer = Delay;
        
        _OS_bTaskDelay = 1;
        _OS_bTaskReady = 1;
        _OS_SET_FSR_CUR_TASK();
        _indf = *((near char*)&OS_state);

    }
}

//______________________________________________________________________________
//******************************************************************************

#endif  // #ifdef OS_TIMER



    










    
    
    
    
    

    
























/****************************************************************************************************
 * 
 * 
 *  T A S K   W O R K   F U N C T I O N S
 *  
 *
 ****************************************************************************************************/

/************************************************************************/
/*                                                                      */
/* Create task in any free descriptor                                   */
/* On return:                                                           */
/*      =1 - OK,                                                        */
/*      =0 - there is no free descriptor                                */
/*                                                                      */
/************************************************************************/

//______________________________________________________________________________
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
#define _OS_CreateTask_DEFINED
//------------------------------------------------------------------------------
bit _OS_CreateTask(_OST_INT_TYPE priority, OST_CODE_POINTER TaskAddr)
{
    OST_TASK_POINTER Task;
    
    OS_Flags.bError = 0;

    #if defined(OS_DISABLE_PRIORITY)
    priority = 0;
    #endif

    Task = (OST_TASK_POINTER)OS_TaskVars;
    _OS_temp = OS_TASKS;
    do {
        if (!Task->State.bEnable)
        {
            ((OST_TASK_STATE*)&priority)->bEnable = 1;
            ((OST_TASK_STATE*)&priority)->bReady = 1;
            
            Task->pTaskPointer = TaskAddr;
            #ifdef OS_ENABLE_TTIMERS
                Task->Timer = 0;
            #endif
            #ifdef __OSA18__
                Task->cTempFSR1 = 0;
            #endif
            *((OS_TASKS_BANK char*)&Task->State) = priority;
            if (Task == _OS_CurTask) *((NEAR char*)&OS_state) = priority;
            _fsr = (_FSR_TYPE)Task;
            
            // Now FSR points to current task's descriptor      
            OS_Flags.bError = 0;
            return 1;
        
        }
        Task ++;
    } while (_OS_temp--);

    // No free descriptor
    OS_Flags.bError = 1;
    return 0;
}

































/******************************************************************************************
 *
 *  P T I M E R S   W O R K  
 *
 ******************************************************************************************/
#ifdef OS_ENABLE_DTIMERS

/************************************************************************/
/*                                                                      */
/************************************************************************/
//------------------------------------------------------------------------------
#define _OS_CreateDTimer_DEFINED
//------------------------------------------------------------------------------
void _OS_CreateDTimer (OST_DTIMER *dtimer)
{
    _OS_temp = OS_DI();
    
    _fsr = (_FSR_TYPE) dtimer;
    _postinc = *((OS_BANK char*)&_OS_DTimers.Flags);
    // Here: bActive is set,
    //       bTimeout is cleared,
    //       bRun is cleared
    //       bNextEnable is copied

    _postinc = *((OS_BANK char*)&_OS_DTimers.Next + 0);
    _postinc = *((OS_BANK char*)&_OS_DTimers.Next + 1);
    _postinc = 0;
    #if  OS_DTIMER_SIZE >= 2
    _postinc = 0;
    #endif
    #if  OS_DTIMER_SIZE == 4
    _postinc = 0;
    _postinc = 0;
    #endif
        


    _OS_DTimers.Next = (OST_DTIMER*)dtimer;
    _OS_DTimers.Flags.bNextEnable = 1;
    
    OS_RI(_OS_temp);
}





/************************************************************************/
/*                                                                      */
/************************************************************************/
//------------------------------------------------------------------------------
#define _OS_DeleteDTimer_DEFINED
//------------------------------------------------------------------------------
void _OS_DeleteDTimer (OST_DTIMER *dtimer)
{
    OST_DTIMER *ptcb;
    
    char flags;
    _fsr = (_FSR_TYPE)dtimer;
    _OS_ClearIndfTimerActive;
    flags = _postinc;
    *((char*)&ptcb + 0) = _postinc;
    *((char*)&ptcb + 1) = _postinc;
    _fsr = (_FSR_TYPE)&_OS_DTimers;
REPEAT:
    if (_OS_CheckPostincTimerNextEnable)
    {
        if (_indf == *((char*)&dtimer + 0))
        {
            if (_preinc == *((char*)&dtimer + 1)){
                _OS_temp = OS_DI();
                _postdec = *((char*)&ptcb + 1);
                _postdec = *((char*)&ptcb + 0);
                if (!((OST_DTIMER_FLAGS*)&flags)->bNextEnable) _OS_ClearIndfTimerNextEnable;
                return;
            }
            _fsr--;
        } 
        asm("   movf    __postinc, w, c     ");
        asm("   movff   __indf, __fsr + 1     ");
        asm("   movwf   __fsr + 0, c      ");
        goto REPEAT;
    }
    
}



#endif  //  OS_ENABLE_DTIMERS


























/****************************************************************************************************
 * 
 * C H E C K   E V E N T   A N D   S E T / C L E A R   R E A D Y   F L A G 
 *
 * (internal system function) 
 *
 ****************************************************************************************************/



//------------------------------------------------------------------------------
#define _OS_CheckEvent_DEFINED
//------------------------------------------------------------------------------
void _OS_CheckEvent (_OST_INT_TYPE bEvent)
{

    OS_Flags.bTimeout = 0;
    _OS_SET_FSR_CUR_TASK();
    if (bEvent) {
        if (_OS_bTaskReady) {
            #ifdef OS_ENABLE_TTIMERS
                _OS_bTaskDelay = 0; // Clear bDelay in temporary variable OS_state
                _indf &= ~0x10;     // Clear bDelay in task descriptor
            #endif
            return;
        }
        _OS_bTaskReady = 1;
    } else {
        _OS_bTaskReady = 0;
    }
    #ifdef OS_ENABLE_TTIMERS
        if (_OS_bTaskTimeout && _OS_bTaskCanContinue) {
            OS_Flags.bTimeout = 1;
            return;
        }
    #endif
    _PIC18_POP();
}


    

        

        






